package com.tan.mypark;

import static android.content.ContentValues.TAG;

import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.hardware.display.DisplayManager;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.Log;
import android.util.TypedValue;
import android.view.Display;
import android.view.LayoutInflater;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.view.animation.AnimationSet;
import android.view.animation.ScaleAnimation;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import androidx.appcompat.app.AppCompatActivity;
import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.constraintlayout.widget.ConstraintSet;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.SnapHelper;
import androidx.recyclerview.widget.LinearSnapHelper;

import com.bumptech.glide.Glide;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.tan.mypark.adapter.PlateLincenerAdapter;
import com.tan.mypark.dialog.DisplaySideDialog;
import com.tan.mypark.manager.WebSocketManager;
import com.tan.mypark.module.AndroidDto;
import com.tan.mypark.module.ParkDisplayConfig;
import com.tan.mypark.module.RestSpaceResponse;
import com.tan.mypark.network.OkHttpUtil;
import com.tan.mypark.utils.AuthUtil;
import com.tan.mypark.utils.ToastUtils;

import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import okhttp3.Call;

public class ParkActivity extends AppCompatActivity {

    private String serialNumber;
    private RecyclerView rvPlateLeft;
    private RecyclerView rvPlateRight;
    private PlateLincenerAdapter leftAdapter;
    private PlateLincenerAdapter rightAdapter;
    private List<AndroidDto> leftList = new ArrayList<>();
    private List<AndroidDto> rightList = new ArrayList<>();

    //WebSocket管理器
    private WebSocketManager plateWebSocketManager;
    private WebSocketManager configWebSocketManager;
    // 认证Token
    private String WS_AUTH_TOKEN = "";

    private Handler scrollHandler;
    private static final long SCROLL_INTERVAL = 3000; // 3秒滚动一次
    //两边列表websocket配置
    private String WS_URL = AuthUtil.getWsUrl() + "/ws-plateAndDirectionToAndroid/websocket";
    private String PLATE_SUBSCRIBE_TOPIC = "/topic/plateAndDirectionToAndroid";
    // 中间区域配置WebSocket配置
    private String CONFIG_WS_URL = AuthUtil.getWsUrl() + "/ws-marqueeDisplayToAndroid/websocket";
    private String CONFIG_SUBSCRIBE_TOPIC = "/topic/marqueeDisplayToAndroid";
    // 新增：Plate主题订阅状态标记（true=已订阅，false=未订阅）
    private boolean isPlateTopicSubscribed = false;
    // 新增：Config主题订阅状态标记（同理）
    private boolean isConfigTopicSubscribed = false;


    // 屏幕可显示的最大条目数量
    private int maxVisibleItemsLeft = 0;
    private int maxVisibleItemsRight = 0;

    //中间区域布局
    private View parkNewThree;
    private TextView tvThreeNewA_zh, tvThreeNewB_zh, tvThreeNewC_zh;
    private ImageView ivThreeNewA, ivThreeNewB, ivThreeNewC;
    private TextView tvThreeNewA_num, tvThreeNewB_num, tvThreeNewC_num;
    private ConstraintLayout view1, view2, view3;

    // 双面屏相关变量
    private int mCurrentDisplayId;
    private String mCurrentDisplaySide;
    private static final String SP_KEY_DISPLAY_MAPPING = "display_mapping";
    private static final String SP_KEY_FIRST_LAUNCH = "first_launch";
    private static final String KEY_DISPLAY_DATA_PREFIX = "display_data_";

    // 用于 SharedPreferences 存储的键
    private static final String SP_NAME = "ParkActivityData";

    // 1. 剩余车位请求相关（取消未完成请求，避免内存泄漏）
    private Call restSpaceCall;

    // 2. 轮询相关配置（15分钟一次请求）
    private Handler pollHandler; // 轮询任务的Handler
    private static final long POLL_INTERVAL = 15 * 60 * 1000; // 15分钟（毫秒）
    private boolean isPolling = false; // 轮询状态标记（避免重复启动）
    private ParkDisplayConfig.DisplayData lastDisplayData; // 保存上次配置（轮询传参用）


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                WindowManager.LayoutParams.FLAG_FULLSCREEN);
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
        setContentView(R.layout.activity_park);

        serialNumber = Settings.Secure.getString(this.getContentResolver(), Settings.Secure.ANDROID_ID);
        Log.d(TAG, "设备序列号: " + serialNumber);

        // 获取当前屏幕的DisplayId
        Display currentDisplay = getWindowManager().getDefaultDisplay();
        mCurrentDisplayId = currentDisplay.getDisplayId();
        Log.d(TAG, "当前屏幕DisplayId: " + mCurrentDisplayId);

        // 初始化当前屏幕的A/B面
        initCurrentDisplaySide();

        //初始化中间区域
        initParkView();

        // 恢复当前面的配置并更新UI
        restoreAndUpdateCurrentSideConfig();

        // 初始化列表
        initRecyclerView();

        // 延迟获取可见条目数量
        new Handler(Looper.getMainLooper()).postDelayed(this::calculateMaxVisibleItems, 500);

        // 初始化WebSocket
        initAllWebSockets();

        // 初始化滚动Handler
        initScrollHandler();
    }


    private void initParkView() {
        parkNewThree = findViewById(R.id.parkNewThree);
        view1 = findViewById(R.id.view1);
        view2 = findViewById(R.id.view2);
        view3 = findViewById(R.id.view3);
        tvThreeNewA_zh = findViewById(R.id.tvThreeNewA_zh);
        tvThreeNewB_zh = findViewById(R.id.tvThreeNewB_zh);
        tvThreeNewC_zh = findViewById(R.id.tvThreeNewC_zh);
        ivThreeNewA = findViewById(R.id.ivThreeNewA);
        ivThreeNewB = findViewById(R.id.ivThreeNewB);
        ivThreeNewC = findViewById(R.id.ivThreeNewC);
        tvThreeNewA_num = findViewById(R.id.tvThreeNewA_num);
        tvThreeNewB_num = findViewById(R.id.tvThreeNewB_num);
        tvThreeNewC_num = findViewById(R.id.tvThreeNewC_num);

        // 给每个View设置Tag，便于日志区分
        view1.setTag("view1");
        view2.setTag("view2");
        view3.setTag("view3");
    }

    private void initRecyclerView() {
        rvPlateLeft = findViewById(R.id.rvPlateLeft);
        rvPlateRight = findViewById(R.id.rvPlateRight);

        LinearLayoutManager leftLayoutManager = new LinearLayoutManager(this);
        LinearLayoutManager rightLayoutManager = new LinearLayoutManager(this);

        leftLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
        rightLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);

        leftAdapter = new PlateLincenerAdapter(this, leftList, "left");
        rightAdapter = new PlateLincenerAdapter(this, rightList, "right");

        rvPlateLeft.setLayoutManager(leftLayoutManager);
        rvPlateLeft.setAdapter(leftAdapter);
        rvPlateRight.setLayoutManager(rightLayoutManager);
        rvPlateRight.setAdapter(rightAdapter);

        // 添加SnapHelper使滚动更平滑
        SnapHelper leftSnapHelper = new LinearSnapHelper();
        SnapHelper rightSnapHelper = new LinearSnapHelper();
        leftSnapHelper.attachToRecyclerView(rvPlateLeft);
        rightSnapHelper.attachToRecyclerView(rvPlateRight);
    }

    // 计算屏幕可显示的最大条目数量
    private void calculateMaxVisibleItems() {
        // 计算左侧列表最大可见条目
        LinearLayoutManager leftLayoutManager = (LinearLayoutManager) rvPlateLeft.getLayoutManager();
        if (leftLayoutManager != null) {
            // 首次计算时，先添加一个临时条目来获取高度
            if (leftList.isEmpty()) {
                AndroidDto tempDto = new AndroidDto();
                tempDto.setPlateNumber("");
                leftList.add(tempDto);
                leftAdapter.notifyItemInserted(0);

                // 等待视图更新后再计算
                new Handler(Looper.getMainLooper()).postDelayed(() -> {
                    View firstItem = leftLayoutManager.findViewByPosition(0);
                    if (firstItem != null) {
                        int itemHeight = firstItem.getHeight();
                        int recyclerViewHeight = rvPlateLeft.getHeight();
                        maxVisibleItemsLeft = recyclerViewHeight / itemHeight;
                        Log.d(TAG, "左侧列表最大可见条目: " + maxVisibleItemsLeft);
                    }
                    // 移除临时条目
                    leftList.remove(0);
                    leftAdapter.notifyItemRemoved(0);
                }, 300);
            }
        }

        // 计算右侧列表最大可见条目
        LinearLayoutManager rightLayoutManager = (LinearLayoutManager) rvPlateRight.getLayoutManager();
        if (rightLayoutManager != null) {
            if (rightList.isEmpty()) {
                AndroidDto tempDto = new AndroidDto();
                tempDto.setPlateNumber("");
                rightList.add(tempDto);
                rightAdapter.notifyItemInserted(0);

                new Handler(Looper.getMainLooper()).postDelayed(() -> {
                    View firstItem = rightLayoutManager.findViewByPosition(0);
                    if (firstItem != null) {
                        int itemHeight = firstItem.getHeight();
                        int recyclerViewHeight = rvPlateRight.getHeight();
                        maxVisibleItemsRight = recyclerViewHeight / itemHeight;
                        Log.d(TAG, "右侧列表最大可见条目: " + maxVisibleItemsRight);
                    }
                    rightList.remove(0);
                    rightAdapter.notifyItemRemoved(0);
                }, 300);
            }
        }
        // 如果计算失败，设置默认值
        if (maxVisibleItemsLeft <= 0) maxVisibleItemsLeft = 5;
        if (maxVisibleItemsRight <= 0) maxVisibleItemsRight = 5;
    }

    private void initScrollHandler() {
        scrollHandler = new Handler(Looper.getMainLooper());
        scrollHandler.postDelayed(new Runnable() {
            @Override
            public void run() {
                autoScrollRecyclerViews();
                scrollHandler.postDelayed(this, SCROLL_INTERVAL);
            }
        }, SCROLL_INTERVAL);
    }

    private void autoScrollRecyclerViews() {
        // 自动滚动左侧列表
        if (leftList.size() > 0) {
            LinearLayoutManager layoutManager = (LinearLayoutManager) rvPlateLeft.getLayoutManager();
            if (layoutManager != null) {
                int currentPos = layoutManager.findFirstVisibleItemPosition();
                int nextPos = (currentPos + 1) % leftList.size();
                rvPlateLeft.smoothScrollToPosition(nextPos);
            }
        }
        // 自动滚动右侧列表
        if (rightList.size() > 0) {
            LinearLayoutManager layoutManager = (LinearLayoutManager) rvPlateRight.getLayoutManager();
            if (layoutManager != null) {
                int currentPos = layoutManager.findFirstVisibleItemPosition();
                int nextPos = (currentPos + 1) % rightList.size();
                rvPlateRight.smoothScrollToPosition(nextPos);
            }
        }
    }

    private void initAllWebSockets() {
        // 初始化车牌推送WebSocket（Plate）
        if (WS_URL != null && !WS_URL.isEmpty()) {
            plateWebSocketManager = new WebSocketManager(
                    getApplicationContext(),
                    WS_URL,
                    WS_AUTH_TOKEN
            );
            plateWebSocketManager.setOnMessageReceivedListener(new PlateWsListener());
            plateWebSocketManager.connect(); // 主动触发首次连接
        } else {
            Log.e(TAG, "Plate WebSocket URL无效，跳过初始化");
        }

        // 初始化配置推送WebSocket（Config）
        if (CONFIG_WS_URL != null && !CONFIG_WS_URL.isEmpty()) {
            configWebSocketManager = new WebSocketManager(
                    getApplicationContext(),
                    CONFIG_WS_URL,
                    WS_AUTH_TOKEN
            );
            configWebSocketManager.setOnMessageReceivedListener(new ConfigWsListener());
            configWebSocketManager.connect(); // 主动触发首次连接
        } else {
            Log.e(TAG, "Config WebSocket URL无效，跳过初始化");
        }
    }

    private class PlateWsListener implements WebSocketManager.OnMessageReceivedListener {
        @Override
        public void onMessage(String topic, String message) {
            Log.d(TAG, "收到Plate主题[" + topic + "]的消息: " + message);
            handlePlateMessage(message);
        }

        @Override
        public void onConnectStatusChanged(boolean isConnected) {
            String status = isConnected ? "车牌推送WebSocket已连接" : "车牌推送WebSocket已断开";
            Log.d(TAG, status);

            // 连接成功时：仅当未订阅时，执行订阅（避免重复订阅）
            if (isConnected && plateWebSocketManager != null && !isPlateTopicSubscribed) {
                // 订阅主题（WebSocketManager内部会自动取消旧订阅）
                plateWebSocketManager.subscribe(PLATE_SUBSCRIBE_TOPIC);
                isPlateTopicSubscribed = true; // 标记为已订阅
                Log.d(TAG, "Plate主题订阅完成");
            }
            // 连接断开时：重置订阅状态（便于重连后重新订阅）
            else if (!isConnected) {
                isPlateTopicSubscribed = false;
            }
        }

        @Override
        public void onError(Throwable throwable) {
            String errorMsg = "车牌推送WebSocket错误: " + (throwable.getMessage() != null ? throwable.getMessage() : "未知错误");
            Log.e(TAG, errorMsg, throwable);
            ToastUtils.toast(ParkActivity.this, errorMsg);
            // 错误时重置订阅状态（避免因错误导致订阅状态异常）
            isPlateTopicSubscribed = false;
        }
    }

    private class ConfigWsListener implements WebSocketManager.OnMessageReceivedListener {
        @Override
        public void onMessage(String topic, String message) {
            Log.d(TAG, "收到Config主题[" + topic + "]的消息: " + message);
            handleConfigMessage(message);
        }

        @Override
        public void onConnectStatusChanged(boolean isConnected) {
            String status = isConnected ? "配置推送WebSocket已连接" : "配置推送WebSocket已断开";
            Log.d(TAG, status);

            if (isConnected && configWebSocketManager != null && !isConfigTopicSubscribed) {
                configWebSocketManager.subscribe(CONFIG_SUBSCRIBE_TOPIC);
                isConfigTopicSubscribed = true;
                Log.d(TAG, "Config主题订阅完成");
            } else if (!isConnected) {
                isConfigTopicSubscribed = false;
            }
        }

        @Override
        public void onError(Throwable throwable) {
            String errorMsg = "配置推送WebSocket错误: " + (throwable.getMessage() != null ? throwable.getMessage() : "未知错误");
            Log.e(TAG, errorMsg, throwable);
            ToastUtils.toast(ParkActivity.this, errorMsg);
            isConfigTopicSubscribed = false;
        }
    }

    private void handlePlateMessage(String message) {
        try {
            Gson gson = new Gson();
            AndroidDto dto = gson.fromJson(message, AndroidDto.class);

            // 校验条件：数据不为空；设备序列号匹配；显示面与当前屏幕一致
            boolean isDtoValid = dto != null;
            boolean isSerialNumber = isDtoValid && serialNumber.equals(dto.getSerialNumber());
            boolean isSideNUmber = isDtoValid && !TextUtils.isEmpty(mCurrentDisplaySide)
                    && mCurrentDisplaySide.equals(dto.getDisplaySide());
            // 验证序列号和显示面
            if (isDtoValid && isSerialNumber && isSideNUmber) {
                // 检查是否过了显示屏
                if ("是".equals(dto.getIsPassDisplay())) {
                    // 移除已过显示屏的数据
                    removePassedItem(dto);
                } else {
                    // 根据方向添加到对应列表
                    addToCorrectList(dto);
                }
            }else {
                if(!isDtoValid){
                    Log.e(TAG, "忽略无效配置数据：AndroidDto为空");
                } else if (!isSerialNumber) {
                    Log.d(TAG, "忽略其他设备的车牌数据：当前设备=" + serialNumber + "，推送设备=" + dto.getSerialNumber());
                } else if (!isSideNUmber) {
                    Log.d(TAG, "忽略其他显示面的车牌数据：当前面=" + mCurrentDisplaySide + "，推送面=" + dto.getDisplaySide() + "，车牌=" + dto.getPlateNumber());
                }
            }

//             // 验证序列号
//            if (serialNumber.equals(dto.getSerialNumber())) {
//                   // 检查是否过了显示屏
//                   if ("是".equals(dto.getIsPassDisplay())) {
//                       // 移除已过显示屏的数据
//                      removePassedItem(dto);
//                  } else {
//                      // 根据方向添加到对应列表
//                       addToCorrectList(dto);
//                 }
//               }
        } catch (Exception e) {
            Log.e(TAG, "解析车牌消息失败: " + e.getMessage());
        }
    }
//    private void handlePlateMessage(String message) {
//        try {
//            Gson gson = new Gson();
//            AndroidDto dto = gson.fromJson(message, AndroidDto.class);
//            if (dto == null) {
//                Log.e(TAG, "解析车牌消息失败：AndroidDto为空");
//                return;
//            }
//
//            // 1. 第一步：校验设备序列号（原有逻辑保留）
//            if (!serialNumber.equals(dto.getSerialNumber())) {
//                Log.d(TAG, "忽略其他设备的车牌数据：当前设备=" + serialNumber + "，推送设备=" + dto.getSerialNumber());
//                return;
//            }
//
//            // 2. 第二步：新增【显示面匹配校验】（与中间区域配置逻辑一致，不匹配直接忽略）
//            // 2.1 检查当前屏幕显示面是否已初始化（未初始化时也忽略，避免异常）
//            if (TextUtils.isEmpty(mCurrentDisplaySide)) {
//                Log.d(TAG, "忽略车牌数据：当前屏幕显示面未初始化（mCurrentDisplaySide为空），车牌=" + dto.getPlateNumber());
//                return;
//            }
//            // 2.2 检查推送消息中的显示面是否有效（不为空且是A/B面）
//            if (TextUtils.isEmpty(dto.getDisplaySide()) || (!"A".equals(dto.getDisplaySide()) && !"B".equals(dto.getDisplaySide()))) {
//                Log.d(TAG, "忽略车牌数据：推送消息显示面无效（值为：" + dto.getDisplaySide() + "），车牌=" + dto.getPlateNumber());
//                return;
//            }
//            // 2.3 校验显示面是否一致（不一致则忽略，与中间区域逻辑完全对齐）
//            if (!mCurrentDisplaySide.equals(dto.getDisplaySide())) {
//                Log.d(TAG, "忽略其他显示面的车牌数据：当前面=" + mCurrentDisplaySide + "，推送面=" + dto.getDisplaySide() + "，车牌=" + dto.getPlateNumber());
//                return;
//            }
//
//            // 3. 第三步：显示面匹配 + 序列号匹配，正常处理车牌数据（原有逻辑保留）
//            // 检查是否过了显示屏
//            if ("是".equals(dto.getIsPassDisplay())) {
//                // 移除已过显示屏的数据
//                removePassedItem(dto);
//            } else {
//                // 根据方向添加到对应列表
//                addToCorrectList(dto);
//            }
//        } catch (Exception e) {
//            Log.e(TAG, "解析车牌消息失败: " + e.getMessage(), e);
//        }
//    }

    private void handleConfigMessage(String message) {
        try {
            // 直接解析为DisplayData
            Gson gson = new Gson();
            ParkDisplayConfig.DisplayData data = gson.fromJson(message, ParkDisplayConfig.DisplayData.class);

            // 校验条件：数据不为空；设备序列号匹配；显示面与当前屏幕一致
            boolean isDataValid = data != null;
            boolean isSerialMatch = isDataValid && serialNumber.equals(data.getDeviceSerial());
            boolean isSideMatch = isDataValid && !TextUtils.isEmpty(mCurrentDisplaySide)
                    && mCurrentDisplaySide.equals(data.getDisplaySide());

            if (isDataValid && isSerialMatch && isSideMatch) {
                // 匹配：保存配置并更新UI
                saveDisplayDataToSP(data);
                // 收到新配置后，立即请求剩余车位并更新UI
                getRestSpaceAndUpdateUI(data);
                // 启动/更新轮询
                startRestSpacePolling(data);
                Log.d(TAG, "收到" + mCurrentDisplaySide + "面配置，更新UI");
            } else {
                // 不匹配：打印日志，不更新UI
                if (!isDataValid) {
                    Log.d(TAG, "忽略无效配置数据");
                } else if (!isSerialMatch) {
                    Log.d(TAG, "忽略其他设备配置：当前设备=" + serialNumber + "，收到设备=" + data.getDeviceSerial());
                } else if (!isSideMatch) {
                    Log.d(TAG, "忽略其他面配置：当前面=" + mCurrentDisplaySide + "，收到面=" + data.getDisplaySide());
                }
            }
        } catch (Exception e) {
            Log.e(TAG, "解析配置消息失败: " + e.getMessage());
        }
    }

    /**
     * 根据DisplayData的areaName请求剩余车位，并更新UI
     *
     * @param displayData 中间区域配置数据（包含areaName和deviceSerial）
     */
    private void getRestSpaceAndUpdateUI(ParkDisplayConfig.DisplayData displayData) {
        //校验areaName（非空+去空格，避免空格导致的非法值）
        String areaName = displayData.getAreaName();
        if (areaName == null || areaName.trim().isEmpty()) {
            Log.e(TAG, "请求剩余车位失败：areaName为空或仅含空格");
            runOnUiThread(() -> updateParkDisplay(displayData, 0));
            return;
        }
        areaName = areaName.trim(); // 关键：去除前后空格（避免" 南区 "这类无效值）
        Log.d(TAG, "当前区域名称（去空格后）：" + areaName);

        // 关键：取消之前未完成的请求（避免轮询任务堆积导致重复请求）
        if (restSpaceCall != null && !restSpaceCall.isCanceled()) {
            restSpaceCall.cancel();
            Log.d(TAG, "取消未完成的剩余车位请求（避免重复）");
        }

        // 2. 构造「表单参数」（替换原来的JSON参数）
        String restSpaceUrl = "http://192.168.1.134:8802/place/getRestSpaceByAreaName";
        Map<String, String> formParams = new HashMap<>();
        formParams.put("areaName", areaName); // 参数名保持areaName（后续可根据后端调整）

        //调用OkHttp的postAsync（表单格式），取消之前的请求（避免重复）
        if (restSpaceCall != null && !restSpaceCall.isCanceled()) {
            restSpaceCall.cancel();
        }
        // 注意：这里改用postAsync（表单），而非postJsonAsync（JSON）
        String finalAreaName = areaName;
        OkHttpUtil.getInstance().postAsync(restSpaceUrl, formParams, new OkHttpUtil.HttpCallback() {
            @Override
            public void onSuccess(String result) {
                //解析响应（用RestSpaceResponse）
                try {
                    Gson gson = new Gson();
                    RestSpaceResponse response = gson.fromJson(result, RestSpaceResponse.class);
                    if (response == null) {
                        Log.e(TAG, "解析剩余车位失败：响应为空");
                        runOnUiThread(() -> updateParkDisplay(displayData, 0));
                        return;
                    }
                    // 校验请求成功 + 数据非空
                    if (response.isSuccess() && response.getData() != null) {
                        int restSpace = Math.max(0, response.getData().getRestSpace());
                        Log.d(TAG, "请求成功：areaName=" + finalAreaName + "，剩余车位=" + restSpace);
                        runOnUiThread(() -> updateParkDisplay(displayData, restSpace));
                    } else {
                        Log.e(TAG, "请求失败（服务器返回错误）：" + response.getMessage());
                        runOnUiThread(() -> updateParkDisplay(displayData, 0));
                    }
                } catch (Exception e) {
                    Log.e(TAG, "解析响应异常：" + e.getMessage(), e);
                    runOnUiThread(() -> updateParkDisplay(displayData, 0));
                }
            }

            @Override
            public void onFailure(Exception e) {
                Log.e(TAG, "请求剩余车位接口异常", e); // 这里不要只打印getMessage()，要打印完整栈
                runOnUiThread(() -> {
                    ToastUtils.toast(ParkActivity.this, "获取车位失败：" + e.getMessage());
                    updateParkDisplay(displayData, 0);
                });
            }
        });
    }

    /**
     * 启动剩余车位轮询（15分钟一次）
     *
     * @param displayData 轮询时需要的配置数据（包含areaName）
     */
    private void startRestSpacePolling(ParkDisplayConfig.DisplayData displayData) {
        // 1. 保存最新配置（轮询时需用areaName请求）
        this.lastDisplayData = displayData;

        // 2. 避免重复启动轮询
        if (isPolling) {
            Log.d(TAG, "剩余车位轮询已在运行，无需重复启动");
            return;
        }

        // 3. 初始化Handler（绑定主线程Looper）
        if (pollHandler == null) {
            pollHandler = new Handler(Looper.getMainLooper());
        }

        // 4. 标记轮询状态并立即执行一次请求（避免等待15分钟才首次获取）
        isPolling = true;
        pollHandler.post(() -> getRestSpaceAndUpdateUI(lastDisplayData));

        // 5. 启动定时轮询（15分钟后开始，之后每15分钟执行一次）
        pollHandler.postDelayed(new Runnable() {
            @Override
            public void run() {
                // 检查轮询状态和配置数据，正常则继续请求
                if (isPolling && lastDisplayData != null) {
                    Log.d(TAG, "执行剩余车位轮询请求");
                    getRestSpaceAndUpdateUI(lastDisplayData);
                    // 循环发送下一次任务
                    pollHandler.postDelayed(this, POLL_INTERVAL);
                } else {
                    Log.d(TAG, "轮询已停止或配置数据为空，终止轮询循环");
                }
            }
        }, POLL_INTERVAL);

        Log.d(TAG, "剩余车位轮询已启动（15分钟一次）");
    }

    /**
     * 停止剩余车位轮询（释放资源，避免内存泄漏）
     */
    private void stopRestSpacePolling() {
        // 1. 标记轮询状态为停止
        isPolling = false;

        // 2. 移除所有未执行的轮询任务并置空Handler
        if (pollHandler != null) {
            pollHandler.removeCallbacksAndMessages(null);
            pollHandler = null;
        }

        // 3. 清空保存的配置数据
        lastDisplayData = null;

        Log.d(TAG, "剩余车位轮询已停止");
    }

    // 检查两个列表中是否已存在相同车牌的记录
    private boolean isPlateExistsInAnyList(String plateNumber) {
        // 检查左侧列表
        for (AndroidDto item : leftList) {
            if (plateNumber.equals(item.getPlateNumber())) {
                return true;
            }
        }
        // 检查右侧列表
        for (AndroidDto item : rightList) {
            if (plateNumber.equals(item.getPlateNumber())) {
                return true;
            }
        }
        return false;
    }

    private void addToCorrectList(AndroidDto dto) {
        runOnUiThread(() -> {
            // 检查车牌是否为空
            if (dto.getPlateNumber() == null || dto.getPlateNumber().isEmpty()) {
                Log.d(TAG, "空车牌，忽略处理");
                return;
            }

            // 检查两个列表中是否已存在相同车牌
            if (isPlateExistsInAnyList(dto.getPlateNumber())) {
                Log.d(TAG, "列表中已存在相同车牌: " + dto.getPlateNumber() + "，忽略新数据");
                return;
            }

            if ("左".equals(dto.getDirection())) {
                leftList.add(dto);
                // 检查是否超出最大可见数量，如果是则移除第一条
                if (leftList.size() > maxVisibleItemsLeft) {
                    leftList.remove(0);
                    leftAdapter.notifyItemRemoved(0);
                }
                leftAdapter.notifyItemInserted(leftList.size() - 1);

                // 如果是第一个item，触发滚动
                if (leftList.size() == 1) {
                    rvPlateLeft.smoothScrollToPosition(0);
                }
            } else if ("右".equals(dto.getDirection()) || "直".equals(dto.getDirection())) {
                rightList.add(dto);
                // 检查是否超出最大可见数量，如果是则移除第一条
                if (rightList.size() > maxVisibleItemsRight) {
                    rightList.remove(0);
                    rightAdapter.notifyItemRemoved(0);
                }
                rightAdapter.notifyItemInserted(rightList.size() - 1);

                // 如果是第一个item，触发滚动
                if (rightList.size() == 1) {
                    rvPlateRight.smoothScrollToPosition(0);
                }
            }
        });
    }

    private void removePassedItem(AndroidDto dto) {
        runOnUiThread(() -> {
            // 从左侧列表移除
            for (int i = 0; i < leftList.size(); i++) {
                if (leftList.get(i).getPlateNumber().equals(dto.getPlateNumber())) {
                    leftList.remove(i);
                    leftAdapter.notifyItemRemoved(i);
                    break;
                }
            }

            // 从右侧列表移除
            for (int i = 0; i < rightList.size(); i++) {
                if (rightList.get(i).getPlateNumber().equals(dto.getPlateNumber())) {
                    rightList.remove(i);
                    rightAdapter.notifyItemRemoved(i);
                    break;
                }
            }
        });
    }

    /**
     * 按A/B面保存中间区域配置
     */
    private void saveDisplayDataToSP(ParkDisplayConfig.DisplayData data) {
        if (data == null || TextUtils.isEmpty(data.getDisplaySide())) {
            Log.e(TAG, "保存配置失败：数据为空或无显示面");
            return;
        }

        // 按面生成SP键（如：display_data_A、display_data_B）
        String spKey = KEY_DISPLAY_DATA_PREFIX + data.getDisplaySide();
        Gson gson = new Gson();
        String json = gson.toJson(data);

        // 保存到SP
        SharedPreferences sp = getSharedPreferences(SP_NAME, Context.MODE_PRIVATE);
        boolean isSaved = sp.edit().putString(spKey, json).commit();

        Log.d(TAG, "保存" + data.getDisplaySide() + "面配置：" + (isSaved ? "成功" : "失败") + "，数据：" + json);
    }

    /**
     * 恢复当前屏幕A/B面的配置
     */
    private void restoreAndUpdateCurrentSideConfig() {
        if (TextUtils.isEmpty(mCurrentDisplaySide)) {
            Log.e(TAG, "恢复配置失败：当前屏幕面未初始化");
            return;
        }

        // 按当前面获取SP键（如：display_data_A）
        String spKey = KEY_DISPLAY_DATA_PREFIX + mCurrentDisplaySide;
        SharedPreferences sp = getSharedPreferences(SP_NAME, Context.MODE_PRIVATE);
        String json = sp.getString(spKey, "");

        // 解析配置并更新UI
        Gson gson = new Gson();
        ParkDisplayConfig.DisplayData savedData = gson.fromJson(json, ParkDisplayConfig.DisplayData.class);
        if (savedData != null) {
            // 恢复配置时也请求一次剩余车位
            getRestSpaceAndUpdateUI(savedData);
            startRestSpacePolling(savedData);
            Log.d(TAG, "恢复当前" + mCurrentDisplaySide + "面配置成功");
        } else {
            Log.d(TAG, "当前" + mCurrentDisplaySide + "面无历史配置");
        }
    }

    /**
     * 初始化当前屏幕的A/B面
     */
    private void initCurrentDisplaySide() {
        SharedPreferences sp = getSharedPreferences(SP_NAME, Context.MODE_PRIVATE);
        boolean isFirstLaunch = sp.getBoolean(SP_KEY_FIRST_LAUNCH, true);
        String displayMappingStr = sp.getString(SP_KEY_DISPLAY_MAPPING, "");

        // 解析已有的DisplayId->A/B面映射
        Map<Integer, String> displayMapping = parseDisplayMapping(displayMappingStr);

        // 检查当前DisplayId是否已有映射
        if (displayMapping.containsKey(mCurrentDisplayId)) {
            mCurrentDisplaySide = displayMapping.get(mCurrentDisplayId);
            Log.d(TAG, "从本地映射获取当前屏幕面：DisplayId=" + mCurrentDisplayId + " → " + mCurrentDisplaySide + "面");
        } else {
            // 无映射：首次启动弹框选择，非首次默认A面并提示
            if (isFirstLaunch) {
//                showDisplaySideSelectDialog(displayMapping);
                new DisplaySideDialog(this, mCurrentDisplayId, displayMapping, new DisplaySideDialog.OnDisplaySideSelectedListener() {
                    @Override
                    public void onSideSelected(String side) {
                        // 处理选择的显示面
                        mCurrentDisplaySide = side;
                        Log.d(TAG, "用户选择当前屏幕为：" + side + "面");
                        // 标记为非首次启动
                        sp.edit().putBoolean(SP_KEY_FIRST_LAUNCH, false).apply();
                    }

                    @Override
                    public void onSaveMapping(Map<Integer, String> mapping, String side) {
                        // 保存更新后的映射关系到SP
                        String newMappingStr = new Gson().toJson(mapping);
                        sp.edit().putString(SP_KEY_DISPLAY_MAPPING, newMappingStr).apply();
                        Log.d(TAG, "已保存新的屏幕映射关系：" + newMappingStr);
                    }
                }
                ).show();
            } else {
                mCurrentDisplaySide = "A";
                ToastUtils.toast(this, "当前屏幕未配置A/B面，默认使用A面（可重启应用重新配置）");
            }
        }
    }

    /**
     * 解析SP中存储的DisplayId->A/B面映射字符串
     */
//    private Map<Integer, String> parseDisplayMapping(String mappingStr) {
//        Map<Integer, String> mapping = new HashMap<>();
//        if (TextUtils.isEmpty(mappingStr)) return mapping;
//
//        String[] pairs = mappingStr.split(",");
//        for (String pair : pairs) {
//            String[] parts = pair.split(":");
//            if (parts.length == 2) {
//                try {
//                    int displayId = Integer.parseInt(parts[0]);
//                    String side = parts[1];
//                    if (side.equals("A") || side.equals("B")) {
//                        mapping.put(displayId, side);
//                    }
//                } catch (NumberFormatException e) {
//                    Log.e(TAG, "解析Display映射失败：" + e.getMessage());
//                }
//            }
//        }
//        return mapping;
//    }
    private Map<Integer, String> parseDisplayMapping(String mappingStr) {
        Map<Integer, String> mapping = new HashMap<>();
        if (TextUtils.isEmpty(mappingStr)) return mapping;
        // 关键修复：用Gson解析（与存储格式一致），替代原字符串分割逻辑
        try {
            Gson gson = new Gson();
            // 注意：Gson解析Map需指定TypeToken，避免泛型擦除
            Type type = new TypeToken<Map<Integer, String>>() {}.getType();
            mapping = gson.fromJson(mappingStr, type);
        } catch (Exception e) {
            Log.e(TAG, "解析Display映射失败：" + e.getMessage(), e);
            // 解析失败时清空映射，避免影响后续逻辑
            mapping.clear();
        }
        return mapping;
    }

//    /**
//     * 首次启动弹框：让用户选择当前屏幕是A面还是B面
//     */
//    private void showDisplaySideSelectDialog(Map<Integer, String> currentMapping) {
//        new AlertDialog.Builder(this)
//                .setTitle("配置屏幕显示面")
//                .setMessage("当前屏幕DisplayId：" + mCurrentDisplayId + "\n请选择此屏幕对应的显示面：")
//                .setPositiveButton("A面", (dialog, which) -> {
//                    saveDisplayMapping(currentMapping, "A");
//                    mCurrentDisplaySide = "A";
//                    dialog.dismiss();
//                })
//                .setNegativeButton("B面", (dialog, which) -> {
//                    saveDisplayMapping(currentMapping, "B");
//                    mCurrentDisplaySide = "B";
//                    dialog.dismiss();
//                })
//                .setCancelable(false)
//                .show();
//    }


//    /**
//     * 保存DisplayId与A/B面的映射到SP
//     */
//    private void saveDisplayMapping(Map<Integer, String> currentMapping, String selectedSide) {
//        // 更新映射表
//        currentMapping.put(mCurrentDisplayId, selectedSide);
//
//        // 构建映射字符串
//        StringBuilder sb = new StringBuilder();
//        for (Map.Entry<Integer, String> entry : currentMapping.entrySet()) {
//            if (sb.length() > 0) sb.append(",");
//            sb.append(entry.getKey()).append(":").append(entry.getValue());
//        }
//
//        // 保存到SP
//        SharedPreferences sp = getSharedPreferences(SP_NAME, Context.MODE_PRIVATE);
//        sp.edit()
//                .putString(SP_KEY_DISPLAY_MAPPING, sb.toString())
//                .putBoolean(SP_KEY_FIRST_LAUNCH, false)
//                .apply();
//
//        Log.d(TAG, "保存Display映射成功：" + sb.toString());
//    }

    /**
     * 更新中间区域显示（新增restSpace参数，接收剩余车位数量）
     *
     * @param data      配置数据
     * @param restSpace 剩余车位数量（0表示获取失败或无车位）
     */
    private void updateParkDisplay(ParkDisplayConfig.DisplayData data, int restSpace) {
        Log.d(TAG, "更新UI：配置数据=" + new Gson().toJson(data) + "，剩余车位=" + restSpace);
        // 重置所有视图
        resetAllViews();

        // 判断需要显示的视图（根据图片路径）
        boolean showView1 = data != null && data.getImagePath1() != null && !data.getImagePath1().isEmpty();
        boolean showView2 = data != null && data.getImagePath2() != null && !data.getImagePath2().isEmpty();
        boolean showView3 = data != null && data.getImagePath3() != null && !data.getImagePath3().isEmpty();

        // 计算显示的视图数量
        int visibleCount = (showView1 ? 1 : 0) + (showView2 ? 1 : 0) + (showView3 ? 1 : 0);

        // 设置视图可见性
        view1.setVisibility(showView1 ? View.VISIBLE : View.GONE);
        view2.setVisibility(showView2 ? View.VISIBLE : View.GONE);
        view3.setVisibility(showView3 ? View.VISIBLE : View.GONE);

        // 调整布局约束（占比和位置）
        adjustLayoutConstraints(showView1, showView2, showView3, visibleCount);

        // 更新视图内容（传入restSpace和data）
        if (data != null) {
            updateViewContent(data, showView1, showView2, showView3, restSpace);
        }

        // 日志打印
        Log.d(TAG, "view1可见：" + showView1 + "，view2可见：" + showView2 + "，view3可见：" + showView3);
    }

    // 重置所有视图状态
    private void resetAllViews() {
        // 隐藏所有视图
        view1.setVisibility(View.GONE);
        view2.setVisibility(View.GONE);
        view3.setVisibility(View.GONE);

        // 重置内容可见性
        tvThreeNewA_zh.setVisibility(View.VISIBLE);
        tvThreeNewA_num.setVisibility(View.VISIBLE);
        tvThreeNewB_zh.setVisibility(View.VISIBLE);
        tvThreeNewB_num.setVisibility(View.VISIBLE);
        tvThreeNewC_zh.setVisibility(View.VISIBLE);
        tvThreeNewC_num.setVisibility(View.VISIBLE);

        // 重置约束
        ConstraintSet constraintSet = new ConstraintSet();
        constraintSet.clone((ConstraintLayout) parkNewThree);

        // 重置三个view的基础约束
        constraintSet.clear(view1.getId(), ConstraintSet.START);
        constraintSet.clear(view1.getId(), ConstraintSet.END);
        constraintSet.clear(view2.getId(), ConstraintSet.START);
        constraintSet.clear(view2.getId(), ConstraintSet.END);
        constraintSet.clear(view3.getId(), ConstraintSet.START);
        constraintSet.clear(view3.getId(), ConstraintSet.END);

        // 重置图片约束
        resetImageConstraints(constraintSet, ivThreeNewA.getId(), tvThreeNewA_zh.getId(), tvThreeNewA_num.getId());
        resetImageConstraints(constraintSet, ivThreeNewB.getId(), tvThreeNewB_zh.getId(), tvThreeNewB_num.getId());
        resetImageConstraints(constraintSet, ivThreeNewC.getId(), tvThreeNewC_zh.getId(), tvThreeNewC_num.getId());

        constraintSet.applyTo((ConstraintLayout) parkNewThree);
    }

    // 重置单个图片的约束
    private void resetImageConstraints(ConstraintSet constraintSet, int imageId, int textId, int numId) {
        constraintSet.clear(imageId, ConstraintSet.START | ConstraintSet.END | ConstraintSet.TOP | ConstraintSet.BOTTOM);
        constraintSet.clear(textId, ConstraintSet.START | ConstraintSet.END | ConstraintSet.TOP | ConstraintSet.BOTTOM);
        constraintSet.clear(numId, ConstraintSet.START | ConstraintSet.END | ConstraintSet.TOP | ConstraintSet.BOTTOM);
    }

    // 调整布局约束
    private void adjustLayoutConstraints(boolean showView1, boolean showView2, boolean showView3, int visibleCount) {
        ConstraintSet constraintSet = new ConstraintSet();
        constraintSet.clone((ConstraintLayout) parkNewThree);

        // 计算单个视图的宽度占比
        float weight = visibleCount > 0 ? 1.0f / visibleCount : 0;

        // 设置每个可见视图的权重
        if (showView1) constraintSet.setHorizontalWeight(view1.getId(), weight);
        if (showView2) constraintSet.setHorizontalWeight(view2.getId(), weight);
        if (showView3) constraintSet.setHorizontalWeight(view3.getId(), weight);

        // 处理view1的位置约束
        if (showView1) {
            constraintSet.connect(view1.getId(), ConstraintSet.START, ConstraintSet.PARENT_ID, ConstraintSet.START);
            // 右侧约束
            if (showView2) {
                constraintSet.connect(view1.getId(), ConstraintSet.END, view2.getId(), ConstraintSet.START);
            } else if (showView3) {
                constraintSet.connect(view1.getId(), ConstraintSet.END, view3.getId(), ConstraintSet.START);
            } else {
                constraintSet.connect(view1.getId(), ConstraintSet.START, ConstraintSet.PARENT_ID, ConstraintSet.START);
            }
        }

        // 处理view2的位置约束
        if (showView2) {
            // 左侧约束
            if (showView1) {
                constraintSet.connect(view2.getId(), ConstraintSet.START, view1.getId(), ConstraintSet.END);
            } else {
                constraintSet.connect(view2.getId(), ConstraintSet.START, ConstraintSet.PARENT_ID, ConstraintSet.START);
            }

            // 右侧约束
            if (showView3) {
                constraintSet.connect(view2.getId(), ConstraintSet.END, view3.getId(), ConstraintSet.START);
            } else {
                constraintSet.connect(view2.getId(), ConstraintSet.END, ConstraintSet.PARENT_ID, ConstraintSet.END);

                // 只显示view2：强制居中
                if (!showView1 && !showView3) {
                    constraintSet.centerHorizontally(view2.getId(), ConstraintSet.PARENT_ID);
                }
            }
        }

        // 处理view3的位置约束
        if (showView3) {
            constraintSet.connect(view3.getId(), ConstraintSet.END, ConstraintSet.PARENT_ID, ConstraintSet.END);

            // 左侧约束
            if (showView2) {
                constraintSet.connect(view3.getId(), ConstraintSet.START, view2.getId(), ConstraintSet.END);
            } else if (showView1) {
                constraintSet.connect(view3.getId(), ConstraintSet.START, view1.getId(), ConstraintSet.END);
            } else {
                constraintSet.connect(view3.getId(), ConstraintSet.END, ConstraintSet.PARENT_ID, ConstraintSet.END);
            }
        }

        constraintSet.applyTo((ConstraintLayout) parkNewThree);
    }

    /**
     * 定义“设备序列号-不需要显示剩余车位的View”映射规则
     * key：设备序列号（deviceSerial）
     * value：该设备下不需要显示数量的View名称列表（如"view1","view2","view3"）
     */
    private Map<String, List<String>> getNoRestSpaceViewRules() {
        Map<String, List<String>> rules = new HashMap<>();
        rules.put("5e55f589fc0e20501", Arrays.asList("view3"));
        rules.put("5e55f589fc0e20502", Arrays.asList("view1", "view2", "view3"));
        rules.put("5e55f589fc0e20503", Arrays.asList("view1"));
        return rules;
    }

    /**
     * 更新视图内容（文字、数字、图标）- 集成剩余车位隐藏规则
     *
     * @param data                  配置数据（含deviceSerial，用于匹配规则）
     * @param showView1/view2/view3 视图是否显示
     * @param restSpace             剩余车位数量
     */
    private void updateViewContent(
            ParkDisplayConfig.DisplayData data,
            boolean showView1,
            boolean showView2,
            boolean showView3,
            int restSpace
    ) {
        // 1. 获取当前设备的隐藏规则（根据deviceSerial匹配）
        Map<String, List<String>> noRestSpaceRules = getNoRestSpaceViewRules();
        List<String> currentDeviceHideViews = noRestSpaceRules.getOrDefault(
                data.getDeviceSerial(), // 用当前设备序列号匹配规则
                new ArrayList<>() // 无匹配规则时，默认显示所有车位
        );

        // 2. 为每个View判断是否需要隐藏数量（true=隐藏，false=显示）
        boolean isHideNum1 = currentDeviceHideViews.contains("view1");
        boolean isHideNum2 = currentDeviceHideViews.contains("view2");
        boolean isHideNum3 = currentDeviceHideViews.contains("view3");

        // 3. 处理view1内容（传入isHideNum1和真实restSpace）
        if (showView1) {
            handleViewContent(
                    view1,
                    ivThreeNewA,
                    tvThreeNewA_zh,
                    tvThreeNewA_num,
                    data.getImagePath1(),
                    data.getText1(),
                    restSpace,
                    false, // view1图标在左
                    isHideNum1,
                    showView1);
        }

        // 4. 处理view2内容
        if (showView2) {
            handleViewContent(
                    view2,
                    ivThreeNewB,
                    tvThreeNewB_zh,
                    tvThreeNewB_num,
                    data.getImagePath2(),
                    data.getText2(),
                    restSpace,
                    false, // view2图标在左
                    isHideNum2,
                    showView2
            );
        }

        // 5. 处理view3内容
        if (showView3) {
            handleViewContent(
                    view3,
                    ivThreeNewC,
                    tvThreeNewC_zh,
                    tvThreeNewC_num,
                    data.getImagePath3(),
                    data.getText3(),
                    restSpace,
                    true, // view3图标在右
                    isHideNum3,
                    showView3
            );
        }
    }

    /**
     * 通用方法：处理单个view的内容显示（支持隐藏数量和真实车位）
     *
     * @param parentView    父布局（view1/view2/view3）
     * @param imageView     图标控件
     * @param textView      文字控件
     * @param numView       数量控件
     * @param imagePath     图标路径
     * @param text          文字内容
     * @param restSpace     剩余车位（int类型，真实数据）
     * @param isIconOnRight 图标是否在文字右侧（view3专用）
     * @param isHideNum     是否隐藏数量（根据规则判断）
     */
    private void handleViewContent(
            ConstraintLayout parentView,
            ImageView imageView,
            TextView textView,
            TextView numView,
            String imagePath,
            String text,
            int restSpace,
            boolean isIconOnRight,
            boolean isHideNum,
            boolean isShowView
    ) {
        imageView.setVisibility(View.VISIBLE);

        boolean isView2 = parentView.getId() == R.id.view2;
        boolean isTextEmpty = text == null || text.isEmpty();
        boolean isNumEmpty = restSpace < 0;
        boolean isNumViewNoContent = isHideNum || isNumEmpty;
        boolean isEmptyState = isTextEmpty && isNumViewNoContent;

        // 图片加载时，根据是否无内容设置尺寸
        int glideWidth = 130;
        int glideHeight = 130;
//        if (isView2 && isShowView && isEmptyState) {
//            glideWidth = dp2px(500);
//            glideHeight = dp2px(500);
//        }

        // 如果Activity已销毁，停止Glide加载
        if (isDestroyed() || isFinishing()) {
            return;
        }

        // 图片显示处理
        if (imagePath != null && !imagePath.isEmpty()) {
            String baseImageUrl = AuthUtil.getUrl();
            String fullImageUrl = baseImageUrl + imagePath;
            Log.d(TAG, "加载图片URL: " + fullImageUrl);

            Glide.with(this)
                    .load(fullImageUrl)
                    .override(glideWidth, glideHeight)
                    .error(R.mipmap.ic_launcher)
                    .into(imageView);
            imageView.setTranslationY(25);
        } else {
            imageView.setImageResource(R.mipmap.ic_launcher);
        }

        // 文字显示处理
//        boolean isTextEmpty = text == null || text.isEmpty();
        textView.setVisibility(isTextEmpty ? View.GONE : View.VISIBLE);
        if (!isTextEmpty) {
            imageView.setTranslationY(25);
            textView.setText(text);
            textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, 60);
        }

//        // 核心逻辑：规则隐藏（isHideNum）优先级 > 剩余车位为0隐藏
//        boolean isNumEmpty = restSpace < 0;
//        boolean isNumViewNoContent = isHideNum || isNumEmpty;
//        boolean isView2 = parentView.getId() == R.id.view2;
//        boolean isEmptyState = isTextEmpty && isNumViewNoContent;

        if (isHideNum) {
            numView.setVisibility(View.GONE);
            Log.d(TAG, parentView.getTag() + "：根据规则隐藏剩余车位数量");
        } else {
            numView.setVisibility(isNumEmpty ? View.GONE : View.VISIBLE);
            if (!isNumEmpty) {
                numView.setText(String.valueOf(restSpace));
                imageView.setTranslationY(-10);
            }
        }

        // 修复约束设置
        ConstraintSet constraintSet = new ConstraintSet();
        constraintSet.clone(parentView);
        // 清除所有旧约束
        constraintSet.clear(imageView.getId(), ConstraintSet.START);
        constraintSet.clear(imageView.getId(), ConstraintSet.END);
        constraintSet.clear(imageView.getId(), ConstraintSet.TOP);
        constraintSet.clear(imageView.getId(), ConstraintSet.BOTTOM);


//        if (isView2 && isShowView) {
//            if (isEmptyState) {
//                // view2显示且无内容：大尺寸居中显示
////                int targetSize = dp2px(500);
////                constraintSet.constrainWidth(imageView.getId(), targetSize);
////                constraintSet.constrainHeight(imageView.getId(), targetSize);
//                constraintSet.centerHorizontally(imageView.getId(), parentView.getId());
//                constraintSet.centerVertically(imageView.getId(), parentView.getId());
//                constraintSet.connect(imageView.getId(), ConstraintSet.TOP, parentView.getId(), ConstraintSet.TOP);
//                constraintSet.connect(imageView.getId(), ConstraintSet.BOTTOM, parentView.getId(), ConstraintSet.BOTTOM);
//                constraintSet.connect(imageView.getId(), ConstraintSet.START, parentView.getId(), ConstraintSet.START);
//                constraintSet.connect(imageView.getId(), ConstraintSet.END, parentView.getId(), ConstraintSet.END);
////                Log.d(TAG, "view2 宽高设置完成：" + targetSize + "x" + targetSize);
//                Log.d(TAG, "view2（无内容）：设置大尺寸图标居中显示");
//            } else {
//                // view2显示且有内容：正常布局
//                if (isTextEmpty) {
//                    // 文字为空、数字不为空
//                    constraintSet.connect(imageView.getId(), ConstraintSet.BOTTOM, numView.getId(), ConstraintSet.TOP);
//                    constraintSet.centerHorizontally(imageView.getId(), numView.getId());
//                    constraintSet.connect(imageView.getId(), ConstraintSet.START, numView.getId(), ConstraintSet.START);
//                    constraintSet.connect(imageView.getId(), ConstraintSet.END, numView.getId(), ConstraintSet.END);
//                } else if (isNumEmpty) { //isNumViewNoContent
//                    // 数字为空、文字不为空
//                    constraintSet.connect(imageView.getId(), ConstraintSet.END, textView.getId(), ConstraintSet.START);
//                    constraintSet.centerVertically(imageView.getId(), textView.getId());
//                    constraintSet.connect(imageView.getId(), ConstraintSet.TOP, parentView.getId(), ConstraintSet.TOP);
//                    constraintSet.connect(imageView.getId(), ConstraintSet.BOTTOM, parentView.getId(), ConstraintSet.BOTTOM);
//                } else {
//                    // 文字和数字都不为空
//                    constraintSet.connect(imageView.getId(), ConstraintSet.END, textView.getId(), ConstraintSet.START);
//                    constraintSet.connect(imageView.getId(), ConstraintSet.BOTTOM, numView.getId(), ConstraintSet.TOP);
//                }
//                Log.d(TAG, "view2（有内容）：正常布局显示");
//            }
//        }
        if (isTextEmpty && isNumEmpty && isView2) {
            // 仅当：view2 + 文字和数字都为空 → 强制图片尺寸200dp并居中
            constraintSet.centerHorizontally(imageView.getId(), parentView.getId());
            constraintSet.centerVertically(imageView.getId(), parentView.getId());
            constraintSet.connect(imageView.getId(), ConstraintSet.TOP, parentView.getId(), ConstraintSet.TOP);
            constraintSet.connect(imageView.getId(), ConstraintSet.BOTTOM, parentView.getId(), ConstraintSet.BOTTOM);
            constraintSet.connect(imageView.getId(), ConstraintSet.START, parentView.getId(), ConstraintSet.START);
            constraintSet.connect(imageView.getId(), ConstraintSet.END, parentView.getId(), ConstraintSet.END);
        } else if (isTextEmpty && isNumEmpty) {
            // 文字和数字都为空：图标在父布局中居中
            constraintSet.centerHorizontally(imageView.getId(), parentView.getId());
            constraintSet.centerVertically(imageView.getId(), parentView.getId());
        } else if (isTextEmpty) {
            // 文字为空、数字不为空：图标在数字正上方居中
            constraintSet.connect(imageView.getId(), ConstraintSet.BOTTOM, numView.getId(), ConstraintSet.TOP);
            constraintSet.centerHorizontally(imageView.getId(), numView.getId());
            constraintSet.connect(imageView.getId(), ConstraintSet.START, numView.getId(), ConstraintSet.START);
            constraintSet.connect(imageView.getId(), ConstraintSet.END, numView.getId(), ConstraintSet.END);
        } else if (isNumEmpty) {
            // 数字为空、文字不为空：根据isIconOnRight决定图标在左/右侧
            if (isIconOnRight) {
                constraintSet.connect(imageView.getId(), ConstraintSet.START, textView.getId(), ConstraintSet.END);
                constraintSet.centerVertically(imageView.getId(), textView.getId());
            } else {
                constraintSet.connect(imageView.getId(), ConstraintSet.END, textView.getId(), ConstraintSet.START);
                constraintSet.centerVertically(imageView.getId(), textView.getId());
            }
            constraintSet.connect(imageView.getId(), ConstraintSet.TOP, parentView.getId(), ConstraintSet.TOP);
            constraintSet.connect(imageView.getId(), ConstraintSet.BOTTOM, parentView.getId(), ConstraintSet.BOTTOM);
        } else {
            // 文字和数字都不为空：根据isIconOnRight决定图标位置
            if (isIconOnRight) {
                // 图标在文字右侧、数字上方（view3专用）
                constraintSet.connect(imageView.getId(), ConstraintSet.START, textView.getId(), ConstraintSet.END);
                constraintSet.connect(imageView.getId(), ConstraintSet.BOTTOM, numView.getId(), ConstraintSet.TOP);
                constraintSet.connect(numView.getId(), ConstraintSet.START, parentView.getId(), ConstraintSet.START);
            } else {
                // 图标在文字左侧、数字上方（view1、view2专用）
                constraintSet.connect(imageView.getId(), ConstraintSet.END, textView.getId(), ConstraintSet.START);
                constraintSet.connect(imageView.getId(), ConstraintSet.BOTTOM, numView.getId(), ConstraintSet.TOP);
//                constraintSet.connect(numView.getId(), ConstraintSet.START, parentView.getId(), ConstraintSet.START,60);
            }
        }

        // 应用约束
        constraintSet.applyTo(parentView);

        parentView.post(() -> {
            Log.d(TAG, parentView.getId() + " 宽度: " + parentView.getWidth() + ", 高度: " + parentView.getHeight());
            Log.d(TAG, imageView.getId() + " 可见性: " + (imageView.getVisibility() == View.VISIBLE ? "VISIBLE" : "GONE"));
        });
    }

    private int dp2px(int dp) {
        return (int) (dp * getResources().getDisplayMetrics().density + 0.5f);
    }

    // 屏幕变化监听器
    private DisplayManager.DisplayListener mDisplayListener = new DisplayManager.DisplayListener() {
        @Override
        public void onDisplayAdded(int displayId) {
        }

        @Override
        public void onDisplayRemoved(int displayId) {
        }

        @Override
        public void onDisplayChanged(int displayId) {
            // 当前屏幕DisplayId变化时，重新初始化
            Display newDisplay = getWindowManager().getDefaultDisplay();
            int newDisplayId = newDisplay.getDisplayId();
            if (newDisplayId != mCurrentDisplayId) {
                Log.d(TAG, "屏幕切换：旧DisplayId=" + mCurrentDisplayId + " → 新DisplayId=" + newDisplayId);
                mCurrentDisplayId = newDisplayId;
                initCurrentDisplaySide();
                restoreAndUpdateCurrentSideConfig();
            }
        }
    };

    @Override
    protected void onResume() {
        super.onResume();
        // 注册屏幕变化监听
        DisplayManager displayManager = (DisplayManager) getSystemService(Context.DISPLAY_SERVICE);
        if (displayManager != null) {
            displayManager.registerDisplayListener(mDisplayListener, null);
        }

        // 重置手动断开标记，允许重连
        if (plateWebSocketManager != null) {
            plateWebSocketManager.resetManualDisconnect(); // 调用WebSocketManager的重置方法
            if (!plateWebSocketManager.isConnected()) {
                plateWebSocketManager.connect();
            }
        }
        // 配置WebSocket同理
        if (configWebSocketManager != null) {
            configWebSocketManager.resetManualDisconnect();
            if (!configWebSocketManager.isConnected()) {
                configWebSocketManager.connect();
            }
        }

        // 恢复轮询
        if (lastDisplayData != null) {
            startRestSpacePolling(lastDisplayData);
        }
    }

    @Override
    protected void onPause() {
        super.onPause();
        // 注销屏幕变化监听
        DisplayManager displayManager = (DisplayManager) getSystemService(Context.DISPLAY_SERVICE);
        if (displayManager != null) {
            displayManager.unregisterDisplayListener(mDisplayListener);
        }

        // 断开WebSocket连接
        if (plateWebSocketManager != null) {
            plateWebSocketManager.disconnect();
        }
        if (configWebSocketManager != null) {
            configWebSocketManager.disconnect();
        }

        // 停止轮询
        stopRestSpacePolling();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        // 停止轮询
        stopRestSpacePolling();

        // 取消剩余车位请求
        if (restSpaceCall != null && !restSpaceCall.isCanceled()) {
            restSpaceCall.cancel();
        }

        // 彻底释放WebSocket资源
        if (plateWebSocketManager != null) {
            plateWebSocketManager.release();
            plateWebSocketManager = null;
        }
        if (configWebSocketManager != null) {
            configWebSocketManager.release();
            configWebSocketManager = null;
        }

        if (scrollHandler != null) {
            scrollHandler.removeCallbacksAndMessages(null);
        }
    }
}
